package com.ifacebox.face.track.ui;

import com.arcsoft.face.FaceFeature;
import com.arcsoft.face.FaceInfo;
import com.arcsoft.face.toolkit.ImageFactory;
import com.arcsoft.face.toolkit.ImageInfo;
import com.ifacebox.face.track.cache.FaceUserCache;
import com.ifacebox.face.track.model.FaceConfig;
import com.ifacebox.face.track.model.FaceUser;
import com.ifacebox.face.track.sevice.FaceConfigService;
import com.ifacebox.face.track.sevice.FaceEnginePooledService;
import com.ifacebox.face.track.sevice.FaceEngineService;
import com.ifacebox.face.track.utils.ImageUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.List;


/**
 * @author znn
 */
public class FaceUserDialog extends JDialog implements FacePageToolBar.Callback {
    private final JList<FaceUser> faceUsers;
    private final DefaultListModel<FaceUser> faceUserModel;
    private final FacePageToolBar facePageToolBar;
    private final FaceEnginePooledService.FaceEnginePool faceEnginePool;

    public FaceUserDialog(JFrame owner, FaceEnginePooledService.FaceEnginePool faceEnginePool) {
        super(owner, owner.getTitle(), true);
        super.setIconImage(owner.getIconImage());
        this.setPreferredSize(new Dimension(120 * 5 + 30, 120 * 5));
        super.setLayout(new BorderLayout());
        super.add(new FaceUserToolBar(this), BorderLayout.NORTH);
        super.add(new JScrollPane(this.faceUsers = new JList<FaceUser>(this.faceUserModel = new DefaultListModel<>()) {{
            this.setVisibleRowCount(-1);
            this.setCellRenderer(new FaceUserCellRenderer());
            this.setLayoutOrientation(JList.HORIZONTAL_WRAP);
            this.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            this.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getClickCount() == MouseEvent.BUTTON2 && faceUsers.getSelectedValue() != null) {
                        try {
                            FaceUser faceUser = FaceUserCache.getInstance().getCache(faceUsers.getSelectedValue());
                            BufferedImage image = ImageUtils.readImage(faceUser.getImage());
                            JOptionPane.showMessageDialog(FaceUserDialog.this, new JLabel(new ImageIcon(image))
                                    , String.format("%dx%d", image.getWidth(), image.getHeight()), JOptionPane.PLAIN_MESSAGE);
                        } catch (Exception ex) {
                            JOptionPane.showMessageDialog(FaceUserDialog.this, ex.toString(), ex.getMessage(), JOptionPane.ERROR_MESSAGE);
                        }
                    }
                }
            });
        }}), BorderLayout.CENTER);
        super.add(this.facePageToolBar = new FacePageToolBar(this), BorderLayout.SOUTH);
        super.pack();
        super.setLocationRelativeTo(null);
        this.faceEnginePool = faceEnginePool;
    }

    @Override
    public void call(int fromIndex, int toIndex) {
        SwingUtilities.invokeLater(this.faceUserModel::removeAllElements);
        for (FaceUser faceUser : FaceUserCache.getInstance().getCaches(fromIndex, toIndex)) {
            SwingUtilities.invokeLater(() -> this.faceUserModel.addElement(faceUser));
        }
    }

    public void refresh() {
        this.facePageToolBar.setTotalSize(FaceUserCache.getInstance().size());
        this.facePageToolBar.refresh();
    }

    public void addFaceUser(File file) throws Exception {
        FaceEngineService faceEngineService = null;
        try {
            ImageInfo imageInfo = ImageFactory.getRGBData(file);
            faceEngineService = this.faceEnginePool.borrowObject();
            List<FaceInfo> faceInfoList = faceEngineService.faceDetect(imageInfo);
            FaceFeature faceFeature = faceEngineService.faceFeature(imageInfo, faceInfoList.get(0));
            BufferedImage image = ImageUtils.cutImage(ImageUtils.readImage(file), faceInfoList.get(0).getRect());
            FaceUser faceUser = new FaceUser(file.getName(), ImageUtils.readImage(image), faceFeature.getFeatureData());
            FaceUserCache.getInstance().addCache(faceUser);
            this.facePageToolBar.setTotalSize(FaceUserCache.getInstance().size());
            this.facePageToolBar.refresh();
        } finally {
            if (faceEngineService != null) {
                this.faceEnginePool.returnObject(faceEngineService);
            }
        }
    }

    public void delFaceUser() {
        List<FaceUser> faceUsers = this.faceUsers.getSelectedValuesList();
        if (faceUsers == null || faceUsers.isEmpty()) {
            JOptionPane.showMessageDialog(this, "请选择一个人像！", this.getTitle(), JOptionPane.ERROR_MESSAGE);
        } else {
            if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(this
                    , String.format("是否删除选中的%d个人像？", faceUsers.size()), this.getTitle(), JOptionPane.YES_NO_OPTION)) {
                for (FaceUser faceUser : faceUsers) {
                    FaceUserCache.getInstance().removeCache(faceUser);
                    this.faceUserModel.removeElement(faceUser);
                }
                this.facePageToolBar.setTotalSize(FaceUserCache.getInstance().size());
                this.facePageToolBar.refresh();
            }
        }
    }

    static class FaceUserCellRenderer extends JLabel implements ListCellRenderer<FaceUser> {
        private static final Dimension FACE_SIZE = new Dimension(100, 100);
        private final static String INFO_FORMAT = "<html>名称：%s<br>特征大小：%.2fKB<br>图像大小：%.2fKB(%dx%d)<br>创建时间：%tF %<tT</html>";
        private final FaceConfigService faceConfigService;
        private FaceConfig faceConfig;

        public FaceUserCellRenderer() {
            this.faceConfigService = new FaceConfigService();
            super.setOpaque(true);
            super.setVerticalAlignment(SwingConstants.CENTER);
            super.setVerticalTextPosition(SwingConstants.BOTTOM);
            super.setHorizontalAlignment(SwingConstants.CENTER);
            super.setHorizontalTextPosition(SwingConstants.CENTER);
        }

        @Override
        public Component getListCellRendererComponent(JList<? extends FaceUser> list, FaceUser value, int index, boolean selected, boolean focus) {
            try {
                if (this.faceConfig == null) {
                    this.faceConfig = this.faceConfigService.readConfig();
                }
                FaceUser faceUser = FaceUserCache.getInstance().getCache(value);
                BufferedImage image = ImageUtils.readImage(faceUser.getImage());
                super.setIcon(new ImageIcon(ImageUtils.scaledImage(image, FACE_SIZE, true)));
                super.setToolTipText(String.format(INFO_FORMAT, faceUser.getName(), faceUser.getData().length / 1024f
                        , faceUser.getImage().length / 1024f, image.getWidth(), image.getWidth()
                        , new File(this.faceConfig.getCacheDir(), value.getName()).lastModified()));
            } catch (Exception e) {
                super.setIcon(null);
            }
            super.setFont(list.getFont());
            super.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            super.setBackground(selected ? list.getSelectionBackground() : list.getBackground());
            super.setForeground(selected ? list.getSelectionForeground() : list.getForeground());
            return this;
        }
    }
}
